package com.youth.youthservice.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.youth.ClientEntity.UserEntity;
import com.youth.commonutils.R;
import com.youth.servicebase.exceptionhandler.GlobalException;
import com.youth.youthservice.client.MemberClient;
import com.youth.youthservice.client.MsmClient;
import com.youth.youthservice.entity.announcement.Announcement;
import com.youth.youthservice.entity.announcement.UserAnnounceTags;
import com.youth.youthservice.entity.announcement.AnnoObject;
import com.youth.youthservice.entity.announcement.Course;
import com.youth.youthservice.entity.vo.annoVo.AnnoUserQuery;
import com.youth.youthservice.entity.vo.annoVo.AnnounceQuery;
import com.youth.youthservice.entity.vo.annoVo.AnnouncementVo;
import com.youth.youthservice.mapper.AnnouncementMapper;
import com.youth.youthservice.service.AnnouncementService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.youth.youthservice.service.EduCourseService;
import com.youth.youthservice.service.UserAnnounceTagsService;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import jdk.nashorn.internal.objects.Global;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;

import static com.youth.commonutils.JwtUtils.APP_SECRET;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author huangqicai
 * @since 2023-03-22
 */
@Service
public class AnnouncementServiceImpl extends ServiceImpl<AnnouncementMapper, Announcement> implements AnnouncementService {

    @Autowired
    private EduCourseService eduCourseService;

    @Autowired
    private UserAnnounceTagsService announceTagsService;

    @Autowired
    private MemberClient memberClient;

    @Autowired
    private MsmClient msmClient;

    /*发布更新公告*/
    @Override
    public R publish(AnnouncementVo announcementvo) {
        /*1.先把公告基本信息保存到数据库*/
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(announcementvo,announcement);
        baseMapper.insert(announcement);
        /*2.获得到公告id,向用户公告表里面增添数据,同时也往用户的收件箱里面发送*/
        String announcementId = announcement.getId();
        if(!StringUtils.isEmpty(announcementvo.getStuArrays())){
            announceTagsService.insertInfo(announcementId,announcementvo.getStuArrays(),announcementvo.getUserType());
        }
        /*3.如果是1级公告，开启异步线程发送短信给用户---后面可以考虑将消息放入到rabbitmq里面*/
        return R.ok();
    }

    /*根据老师id查询课程学生信息*/
    @Override
    public R selectCourseStu() {
        /*1.根据老师id得到所有的课程id*/
        ArrayList<Course> courses =eduCourseService.selectCourse();
        return R.ok().data("options",courses);

    }

    /*分页条件查询公告列表*/
    @Override
    public R selectPage(long current, long limit, AnnounceQuery announceQuery) {
        /*1.为此次查询附上条件*/
        QueryWrapper<Announcement> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(announceQuery.getPriority())){
            wrapper.eq("priority", announceQuery.getPriority());
        }
        if(!StringUtils.isEmpty(announceQuery.getTitle())){
            wrapper.like("title", announceQuery.getTitle());
        }
        if(!StringUtils.isEmpty(announceQuery.getUserType())){
            wrapper.eq("user_type", announceQuery.getUserType());
        }
        if(!StringUtils.isEmpty(announceQuery.getBeginTime())){
            wrapper.gt("gmt_create", announceQuery.getBeginTime());
        }
        if(!StringUtils.isEmpty(announceQuery.getEndTime())){
            wrapper.lt("gmt_create", announceQuery.getEndTime());
        }
        /*2.开始分页查询*/
        IPage<Announcement> page = baseMapper.selectPage(new Page<Announcement>(current,limit), wrapper);
        HashMap<String, Object> map = new HashMap<>();
        map.put("rows",page.getRecords());
        map.put("total",page.getTotal());
        return R.ok().data(map);
    }

    /*删除公告执行的方法*/
    @Override
    @Transactional
    public R deleteAnno(String annoId) {
        /*1.根据公告id删除公告表里面的信息*/
        int count = baseMapper.deleteById(annoId);
        if(count>0){
            /*2.根据公告id删除用户公告表里面的记录数据，并删除redis里面的数据*/
            boolean flag=announceTagsService.deleteInfo(annoId);
            if(flag){
                return R.ok();
            }
        }
        return R.error();
    }

    /*根据公告id查询公告信息*/
    @Override
    public R selectInfo(String annoId) {
        Announcement announcementRes = baseMapper.selectById(annoId);
        /*根据公告id查询其阅读量*/
        String views=announceTagsService.selectUserViews(annoId);
        announcementRes.setViewCount(views);
        return R.ok().data("anno",announcementRes);

    }

    /*根据公告id查询公告对象的集合-(条件查询)*/
    @Override
    public R selectUsers(String annoId, AnnoUserQuery annoUserQuery) {
        /*最终返回的结果集*/
        ArrayList<AnnoObject> annoObjects = new ArrayList<>();
        /*2.根据公告id去查询用户id集合*/
        List<UserAnnounceTags> userAnnounceTags = announceTagsService.selectUsersByannoId(annoId, annoUserQuery.getFlag());
        if(userAnnounceTags!=null){
            /*2.根据用户id去查询*/
            userAnnounceTags.stream().forEach(new Consumer<UserAnnounceTags>() {
                @Override
                public void accept(UserAnnounceTags userAnnounceTag) {
                    /*根据用户id去查询用户信息,远程调用*/
                    HashMap<String, String> map = new HashMap<>();
                    map.put("userId",userAnnounceTag.getUserId());
                    map.put("userName",annoUserQuery.getUserName());
                    map.put("userPhone",annoUserQuery.getUserPhone());
                    UserEntity userEntity = (UserEntity)memberClient.ByIdGetUser(map);
                    if(userEntity==null){
                        return;/*跳出本次循环*/
                    }
                    AnnoObject annoObject = new AnnoObject();
                    BeanUtils.copyProperties(userEntity, annoObject);
                    annoObject.setFlag(userAnnounceTag.getReadFlag());
                    annoObjects.add(annoObject);
                }
            });
        }
        return R.ok().data("annoObjects",annoObjects);
    }

    /*根据手机号发送短信，提醒用户*/
    @Override
    public R sendMsmToStu(String phone) {
        msmClient.sendSmsAnno(phone);
        return R.ok();
    }

    /*更新公告信息执行的方法*/
    @Override
    @Transactional
    public R updateAnno(String annoId, AnnouncementVo announcementVo) {
        /*1.根据公告id去更新公告的基本信息*/
        Announcement announcement = new Announcement();
        BeanUtils.copyProperties(announcementVo, announcement);
        baseMapper.update(announcement, new QueryWrapper<Announcement>().eq("id", annoId));
        /*2.获取学生id集合,修改userTags*/
        ArrayList<String> stuArrays = announcementVo.getStuArrays();
        announceTagsService.insertInfo(annoId,announcementVo.getStuArrays(),announcementVo.getUserType());
        return R.ok();
    }

    /*------------------------前台相关api---------------------------------*/

    /*根据用户id得到公告列表*/
    @Override
    public R selectListAnno(long current, long limit, AnnounceQuery announceQuery, HttpServletRequest request) {
        HashMap<String, Object> map = new HashMap<>();
        String token = request.getHeader("token");
        if(token == null){
            throw new GlobalException(20002,"您尚未登录");
        }
        /*解析token获取当前登录的用户*/
        Jws<Claims> claimsJws = Jwts.parser().setSigningKey(APP_SECRET).parseClaimsJws(token);
        String userId = (String) claimsJws.getBody().get("id");
        map.put("userId",userId);
        map.put("announceQuery",announceQuery);
        IPage<Announcement> announcementIPage = baseMapper.selectListAnno(new Page<>(current, limit),map);
        /*返回给前端数据*/
        HashMap<String, Object> mapRes = new HashMap<>();
        mapRes.put("rows", announcementIPage.getRecords());
        mapRes.put("total", announcementIPage.getTotal());
        return R.ok().data(mapRes);
    }


}
